package com.eian.boot.module.system.user.service;

import com.eian.boot.common.constants.ErrorMessage;
import com.eian.boot.common.core.enums.CommonEnum;
import com.eian.boot.common.core.exception.ExceptionHelper;
import com.eian.boot.common.core.utils.BeanCopierUtils;
import com.eian.boot.common.id.IdHelper;
import com.eian.boot.module.system.associations.user.role.service.UserRoleRelationService;
import com.eian.boot.module.system.permission.service.PermissionCacheService;
import com.eian.boot.module.system.post.model.vo.PostSimpleVO;
import com.eian.boot.module.system.post.service.SysPostService;
import com.eian.boot.module.system.role.model.vo.RoleVO;
import com.eian.boot.module.system.role.service.SysRoleService;
import com.eian.boot.module.system.user.mapper.SysUserMapper;
import com.eian.boot.module.system.user.model.dto.CreateUserRequest;
import com.eian.boot.module.system.user.model.dto.UserQueryRequest;
import com.eian.boot.module.system.user.model.dto.UserUpdateRequest;
import com.eian.boot.module.system.user.model.entity.SysUserEntity;
import com.eian.boot.module.system.user.model.vo.UserDetailVO;
import com.eian.boot.module.system.user.model.vo.UserListVO;
import com.eian.boot.mybatis.core.page.PageResult;
import com.eian.boot.mybatis.core.service.BaseService;
import com.eian.boot.security.utils.PwdKit;
import com.eian.boot.security.utils.SessionHelper;
import com.mybatisflex.core.paginate.Page;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.eian.boot.common.constants.ErrorMessage.User;
import static com.eian.boot.table.Tables.sys_role;
import static com.eian.boot.table.Tables.sys_user;

/**
 * 用户表 服务层实现。
 *
 * @author alex.meng
 * @since 1.0.0
 */
@Service
@AllArgsConstructor
public class SysUserService extends BaseService<SysUserMapper, SysUserEntity> {
    private final UserRoleRelationService userRoleRelationService;
    private final SysRoleService roleService;
    private final SysPostService postService;
    private final PermissionCacheService cacheService;

    private SysUserEntity checkUserValid(Long id) {
        SysUserEntity user = this.getById(id);
        ExceptionHelper.ifNull(user, ErrorMessage.User.USER_NOT_EXIST);
        return user;
    }

    /**
     * @author alex.meng
     * @description 创建用户
     **/
    public void createUser(CreateUserRequest params) {
        SysUserEntity user = BeanCopierUtils.copy(params, SysUserEntity.class);

        boolean exists = this.queryChain().from(sys_user).where(sys_user.username.eq(user.getUsername())).exists();
        ExceptionHelper.ifTrue(exists, ErrorMessage.User.USERNAME_EXIST);

        if (StringUtils.isNotBlank(user.getTelephone())) {
            exists = this.queryChain().from(sys_user).where(sys_user.telephone.eq(user.getTelephone())).exists();
            ExceptionHelper.ifTrue(exists, ErrorMessage.User.TELEPHONE_HAS_BIND);
        }
        if (StringUtils.isNotBlank(user.getEmail())) {
            exists = this.queryChain().from(sys_user).where(sys_user.email.eq(user.getEmail())).exists();
            ExceptionHelper.ifTrue(exists, ErrorMessage.User.EMAIL_HAS_BIND);
        }

        user.setPassword(PwdKit.encrypt(user.getPassword()));
        save(user);
    }

    /**
     * @author alex.meng
     * @description 获取用户详情
     **/
    public UserDetailVO getUserDetail(Long id) {
        SysUserEntity user = checkUserValid(id);
        UserDetailVO userDetail = BeanCopierUtils.copy(user, UserDetailVO.class);

        // 先获取角色ID
        List<Long> roleIds = userRoleRelationService.getRoleIdsByUserId(user.getId());

        // 再查询角色详情
        if (!roleIds.isEmpty()) {
            List<RoleVO> userRoles = roleService.queryChain()
                    .from(sys_role)
                    .where(sys_role.id.in(roleIds))
                    .listAs(RoleVO.class);
            userDetail.setRoles(userRoles);
        } else {
            userDetail.setRoles(List.of());
        }

        // 查询用户岗位
        List<PostSimpleVO> userPosts = postService.getUserPosts(user.getId());
        userDetail.setPosts(userPosts);

        return userDetail;
    }

    /**
     * @author alex.meng
     * @description 更新用户信息
     **/
    public void updateUser(UserUpdateRequest params) {
        SysUserEntity user = checkUserValid(params.getId());

        // 检查邮箱是否重复
        if (StringUtils.isNotBlank(params.getEmail()) && !params.getEmail().equals(user.getEmail())) {
            boolean emailExists = this.queryChain()
                    .from(sys_user)
                    .where(sys_user.email.eq(params.getEmail()).and(sys_user.id.ne(user.getId())))
                    .exists();
            ExceptionHelper.ifTrue(emailExists, ErrorMessage.User.EMAIL_HAS_BIND);
        }

        // 检查手机号是否重复
        if (StringUtils.isNotBlank(params.getTelephone()) && !params.getTelephone().equals(user.getTelephone())) {
            boolean phoneExists = this.queryChain()
                    .from(sys_user)
                    .where(sys_user.telephone.eq(params.getTelephone()).and(sys_user.id.ne(user.getId())))
                    .exists();
            ExceptionHelper.ifTrue(phoneExists, ErrorMessage.User.TELEPHONE_HAS_BIND);
        }

        BeanCopierUtils.copy(params, user);
        this.updateById(user);
    }

    /**
     * @author alex.meng
     * @description 获取用户列表（分页）
     * 应用数据权限控制，基于用户所在部门过滤
     **/
    @com.eian.boot.common.annotation.DataScope(userAlias = "t_sys_user")
    public PageResult<UserListVO> getUserList(UserQueryRequest params) {
        Page<SysUserEntity> page = this.queryChain()
                .from(sys_user)
                .where(sys_user.username.like(params.getUsername())
                        .and(sys_user.nickname.like(params.getNickname()))
                        .and(sys_user.email.like(params.getEmail()))
                        .and(sys_user.telephone.like(params.getTelephone()))
                        .and(sys_user.status.eq(params.getStatus()))
                )
                .orderBy(sys_user.id, false)
                .page(params.buildPage());
        return PageResult.build(page, UserListVO.class);
    }

    /**
     * @author alex.meng
     * @description 更新密码
     **/
    public void updatePassword(Long userId, String oldPassword, String newPassword) {
        SysUserEntity user = checkUserValid(userId);
        if (StringUtils.isNotBlank(oldPassword)) {
            boolean match = PwdKit.match(oldPassword, user.getPassword());
            ExceptionHelper.ifTrue(!match, ErrorMessage.User.OLD_PASSWORD_ERROR);
        }
        user.setPassword(PwdKit.encrypt(newPassword));
        this.updateById(user);

        SessionHelper.logout(userId);
    }

    /**
     * @author alex.meng
     * @description 重置随机密码
     **/
    public String resetRandomPassword(Long userId) {
        String randomPwd = IdHelper.simpleUuid().substring(16);
        updatePassword(userId, null, randomPwd);
        return randomPwd;
    }

    /**
     * @author alex.meng
     * @description 删除用户
     **/
    @Transactional
    public void deleteUser(Long userId) {
        //=== 删除用户信息
        SysUserEntity user = checkUserValid(userId);
        this.removeById(user);
        //=== 级联删除用户角色关系（会触发事件清理缓存）
        userRoleRelationService.cascadeDeleteByUserId(userId);
    }

    /**
     * @author alex.meng
     * @description 更新用户状态
     **/
    public void updateUserStatus(Long userId, Integer status) {
        SysUserEntity user = checkUserValid(userId);
        user.setStatus(status);
        boolean result = this.updateById(user);
        if (result && status.equals(CommonEnum.DISABLED.getValue())) {
            SessionHelper.logout(user.getId());
            cacheService.clearUserAllCache(userId);
        }
    }

    /**
     * @author alex.meng
     * @description 分配用户角色
     **/
    @Transactional(rollbackFor = Exception.class)
    public void assignUserRoles(Long userId, List<Long> roleIds) {
        // 业务验证：用户存在性
        SysUserEntity user = checkUserValid(userId);

        // 业务验证：角色有效性
        long validRoleCount = roleService.queryChain()
                .from(sys_role)
                .where(sys_role.id.in(roleIds).and(sys_role.status.eq(CommonEnum.ENABLED.getValue())))
                .count();
        ExceptionHelper.ifTrue(validRoleCount != roleIds.size(), User.ROLE_INVALID);

        // 委托给关系服务处理（会触发事件清理缓存）
        userRoleRelationService.assignUserRoles(user.getId(), roleIds);
    }

}